package com.newlink.building.activities

import android.app.Service
import android.content.Context
import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.media.AudioManager
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.PersistableBundle
import android.os.SystemClock
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.ImageView
import android.widget.RelativeLayout
import android.widget.TextView
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.alibaba.android.arouter.facade.annotation.Route
import com.alibaba.android.arouter.launcher.ARouter
import com.newlink.building.library_rino.ConnectionController
import com.newlink.building.library_rino.listener.RinoEventListenerStub
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.newlink.building.common_base.base.NL_BaseActivity
import com.newlink.building.common_base.base.BaseApplication.Companion.getDeviceDataByUsername
import com.newlink.building.common_base.constant.NL_Key
import com.newlink.building.common_base.constant.Base_RouterPath
import com.newlink.building.common_base.event.MessageEvent
import com.newlink.building.common_base.event.OpenDoorResultBean
import com.newlink.building.common_base.event.TYPE_APP_OPEN_DOOR_RESULT
import com.newlink.building.common_base.event.TYPE_APP_SHOW_LOADING
import com.newlink.building.common_base.event.TYPE_CALL_SEND_CREATE_CHANNEL_RESULT_MONITOR
import com.newlink.building.common_base.event.TYPE_CALL_SEND_CREATE_CHANNEL_RESULT_TRYING
import com.newlink.building.common_base.event.TYPE_CALL_UPDATE_CHANNEL_RESULT
import com.newlink.building.common_base.ext.showToast
import com.newlink.building.common_base.model.bean.DoorData
import com.newlink.building.common_base.utils.Base_DensityUtil
import com.newlink.building.common_base.utils.DialogUtil
import com.newlink.building.common_base.utils.NLog
import com.newlink.building.common_base.utils.MqttDoorOperator
import com.newlink.building.common_base.utils.ScreenUtil
import com.newlink.building.common_base.utils.StatusBarUtil
import com.newlink.building.common_base.utils.StatusBarUtil.DEFAULT_STATUS_BAR_ALPHA
import com.newlink.building.common_base.widget.SpaceItemDecoration
import com.newlink.building.NL_App.Companion.coreContext
import com.newlink.building.R
import com.newlink.building.activities.call.Module_Phone_CallActivity
import com.newlink.building.activities.call.adapter.Module_Phone_DtmfAdapter
import com.newlink.building.activities.call.viewmodels.CallViewModel
import com.newlink.building.activities.call.viewmodels.CallViewModelFactory
import com.newlink.building.adapter.Module_Phone_FuctionKeyAdapter
import com.newlink.building.bean.Module_Phone_FunctionKey
import com.newlink.building.bean.Module_Phone_MonitorFunctionType
import com.newlink.building.compatibility.Module_Phone_Compatibility
import com.newlink.building.databinding.MonitorActivityBinding
import com.newlink.building.manager.Module_Phone_VoipController
import com.newlink.building.utils.Module_Phone_AudioRouteUtils
import com.newlink.building.utils.Module_Phone_CountdownWorker
import com.newlink.building.utils.Module_Phone_VolumeChangeHelper
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import org.linphone.core.Call
import org.linphone.core.Core
import org.linphone.core.CoreListenerStub
import org.linphone.core.tools.Log
import java.text.SimpleDateFormat
import java.util.Timer
import java.util.TimerTask

/**
 * Created by xiaodong on 2022/9/15.
 */
@Route(path = Base_RouterPath.PATH_MONITOR)
class Module_Phone_MonitorActivityNL : NL_BaseActivity() {
    private val manager: Module_Phone_VoipController = Module_Phone_VoipController.get()
    private var duration: Long = 200L
    private var countDownTime: Long = 30000L
    private var loadVideoTimeout: Long = 20000L
    private var delayTime: Long = 8000L
    private var isMovedDown: Boolean = false
    private var isMute: Boolean = true
    private var isStreamsRunning: Boolean = false
    private var isRecording: Boolean = false
    private lateinit var funcationKeyData: MutableList<Module_Phone_FunctionKey>
    private var timer: Timer? = null
    private val sHandler: Handler = Handler(Looper.getMainLooper())
    private var centerTitle: TextView? = null
    private var currentCallId: String? = null
    private var countdownWorker: Module_Phone_CountdownWorker? = null
    private var ibFullscreen: ImageView? = null
    private var statusBarSpace: View? = null

    //加入通道是否成功
    private var joinChannelSuccess = false

    //是否为远端更新channelName事件
    private var remoteUpdateChannelEvent = false
    private var onFirstRemoteVideoFrame = false
    private var tempScreenshotFileName: String = "temp_screenshot.jpg"

    //支持的功能类型列表,移除了静音功能
    private var supportFunctionTypes =
        Module_Phone_MonitorFunctionType.values().filterNot { it == Module_Phone_MonitorFunctionType.MUTE }

    private lateinit var viewModel: CallViewModel

    private val rinoManager: ConnectionController by lazy {
        ConnectionController.getInstance(
            applicationContext
        )
    }

    private val functionKeyAdapter: Module_Phone_FuctionKeyAdapter by lazy {
        Module_Phone_FuctionKeyAdapter()
    }

//    override fun attachLayoutRes(): Int = R.layout.monitor_activity

    private lateinit var mBinding: MonitorActivityBinding
    override fun attachLayoutRes(): View {
        mBinding = MonitorActivityBinding.inflate(layoutInflater)
        return mBinding.root
    }

    private val mDialog by lazy {
        DialogUtil.getWaitDialog(this)
    }

    private fun showLoading() {
        if (mDialog.window != null) {
            mDialog.show()
        }
    }

    private fun hideLoading() {
        if (mDialog.window != null) {
            mDialog.dismiss()
        }
    }

    override fun initData() {
        StatusBarUtil.setColor(this, mThemeColor, 0)
        requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
        funcationKeyData = getFunctionKeyData()
        if (intent?.action.equals("endCall")) {
            finish()
        }

        StatusBarUtil.setTranslucent(this, DEFAULT_STATUS_BAR_ALPHA)
    }

    private fun getFunctionKeyData(): MutableList<Module_Phone_FunctionKey> {
        val list = mutableListOf<Module_Phone_FunctionKey>()
        if (isFullScreen) {
            val openDoorFunctionKey = Module_Phone_FunctionKey(
                R.string.function_opendoor,
                R.drawable.icon_opendoor,
                R.drawable.icon_opendoor_landscape,
                1
            )
//            for (i in types.indices) {
//                val functionType = types[i]
//                list.add(FunctionKey(functionType.stringRes,
//                    functionType.drawableRes,
//                    functionType.drawableResLandscape,
//                    functionType.code))
//            }
            for (i in supportFunctionTypes.indices) {
                val functionType = supportFunctionTypes[i]
                if (functionType == Module_Phone_MonitorFunctionType.MUTE) {
                    list.add(
                        Module_Phone_FunctionKey(
                            functionType.stringRes,
                            if (isMute) R.mipmap.ic_speaker_close else R.mipmap.ic_speaker,
                            if (isMute) R.mipmap.ic_speaker_close_landscape else R.mipmap.ic_speaker_landscape,
                            functionType.code
                        )
                    )
                } else {
                    list.add(
                        Module_Phone_FunctionKey(
                            functionType.stringRes,
                            functionType.drawableRes,
                            functionType.drawableResLandscape,
                            functionType.code
                        )
                    )
                }
            }

            list.add(1, openDoorFunctionKey)

        } else {
            for (i in supportFunctionTypes.indices) {
                var functionType = supportFunctionTypes[i]
                if (functionType == Module_Phone_MonitorFunctionType.MUTE) {
                    list.add(
                        Module_Phone_FunctionKey(
                            functionType.stringRes,
                            if (isMute) R.mipmap.ic_speaker_close else R.mipmap.ic_speaker,
                            if (isMute) R.mipmap.ic_speaker_close_landscape else R.mipmap.ic_speaker_landscape,
                            functionType.code
                        )
                    )
                } else {
                    list.add(
                        Module_Phone_FunctionKey(
                            functionType.stringRes,
                            functionType.drawableRes,
                            functionType.drawableResLandscape,
                            functionType.code
                        )
                    )
                }
            }
        }
        return list
    }

    override fun initView() {
        coreContext.inMonitorCallActivity = true
        statusBarSpace = findViewById<View>(R.id.status_bar_space)
        statusBarSpace?.postDelayed({
            NLog.e("===========update status bar height============")
            updateStatusbar()
            statusBarSpace?.requestLayout()
        }, 600)

//        initVolumeChangeHelper()
        ibFullscreen = findViewById<ImageView>(R.id.ib_fullscreen)
        mDialog.window?.setFlags(
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
        )
        showLoading()
        val currentCall: Call? = findMonitorCall()
        currentCallId = currentCall?.callLog?.callId
        if (currentCall == null) {
            Log.e("[Call Activity] Couldn't find call in state Incoming")
            if (isTaskRoot) {
                Log.i("[Call Activity] Task is root, starting MainActivity")
                // When resuming app from recent tasks make sure MainActivity will b
                //
                ARouter.getInstance().build(Base_RouterPath.PATH_HOME)
                    .withFlags(Intent.FLAG_ACTIVITY_NEW_TASK).navigation()
//                val intent = Intent()
//                intent.setClass(this, LinphoneMainActivity::class.java)
//                intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
//                startActivity(intent)
            }
            finish()
            return
        }
        viewModel = ViewModelProvider(
            this,
            CallViewModelFactory(currentCall)
        )[CallViewModel::class.java]
        muteDevice(true)
        rinoManager.setMicEnabled(false)
//        startTimer()
        val remoteSipAccount = Module_Phone_VoipController.get().getRemoteSipAccount()
        val displayName =
            getDeviceDataByUsername(remoteSipAccount)?.devName ?: Module_Phone_VoipController.get()
                .getRemoteUsername()

        centerTitle = findViewById(R.id.tv_title)
        centerTitle?.text = displayName
        functionKeyAdapter.run {
            addChildClickViewIds()
            setOnItemChildClickListener { adapter, _, position ->
                val type = funcationKeyData[position]
                when (type.code) {
//                    0 -> manager.takeScreenshot(this@MonitorActivity, displayName)
                    0 -> {
                        takeScreenshot(displayName)
//                        if (PermissionHelper.get().hasWriteExternalStoragePermission()) {
//                            Log.e("[jake] .. has ... write external storage .... ")
//                            takeScreenshot(displayName)
//                        } else {
//                            Log.e("[jake] .. no.....  write external storage .... ")
//                            ActivityCompat.requestPermissions(this@MonitorActivity,
//                                arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 100)
//                        }
                    }

                    1 -> {
//                        val mac = getDeviceDataByUsername(remoteUsername)?.mac ?: ""
////                        EventBus.getDefault().post(OpenDoorActionEvent(mac, 1))
//                        DoorOperator.sendOpenDoorAction(userId , mac, 1, 0)
                        val currentDevice = getDeviceDataByUsername(remoteSipAccount)
                        currentDevice?.doors?.let {
                            if (it.size == 1) {
                                var doorNum = currentDevice.doors?.get(0)?.doorNo ?: 1
                                openDoor(currentDevice.mac, doorNum)
                            } else {
                                showBottomSheetDialog(currentDevice.mac, it)
                            }
                        }
                    }

                    2 -> {
                        safeHangup()
                    }

                    3 -> {

                        muteDevice(!isMute)
                        val drawableRes =
                            if (isMute) R.mipmap.ic_speaker else R.mipmap.ic_speaker_close
                        val drawableResLand =
                            if (isMute) R.mipmap.ic_speaker_landscape else R.mipmap.ic_speaker_close_landscape
                        val stringRes =
                            if (isMute) R.string.function_speaker else R.string.function_mute
                        type.drawableRes = drawableRes
                        type.drawableResLandscape = drawableResLand
                        type.stringRes = stringRes
                        notifyDataSetChanged()
                        isMute = !isMute
                    }

                    4 -> {
                        updateVideoCallParams()
                        Intent(context, Module_Phone_CallActivity::class.java).run {
                            startActivity(this)
                        }
                        finish()
//                        manager.toggleRecording(!isRecording)
//                        isRecording = !isRecording
//                        type.stringRes =
//                            if (isRecording) R.string.video_is_recording else R.string.function_video_recording
                    }

                    else ->
                        showToast(resources.getString(funcationKeyData[position].stringRes))
                }
                adapter.notifyDataSetChanged()
            }
            setNewData(funcationKeyData)
        }

        mBinding.rlFunctions.run {
            adapter = functionKeyAdapter
            layoutManager = GridLayoutManager(context, supportFunctionTypes.size)
        }

        findViewById<RelativeLayout>(R.id.ib_fullscreen_layout).setOnClickListener {
            MainScope().launch {
                delay(800)
                toggleFullScreen()
            }
        }

        mBinding.bottomControllerOpenDoor.setOnClickListener(onClickListener)
        mBinding.ibSettings.setOnClickListener(onClickListener)
        mBinding.monitorTitleBar.ivBack.setOnClickListener(onClickListener)
        mBinding.remoteVideoSurface.setOnClickListener(onClickListener)
//        mBinding.remoteVideoSurface.isOpaque = false
//        manager.setVideoWindowId(mBinding.remoteVideoSurface, mBinding.localPreviewVideoSurface)
        coreContext.core.addListener(coreListener)
        rinoManager.addRinoEventListener(rinoEventListener)
//        startTimer()
    }

    override fun onSaveInstanceState(outState: Bundle, outPersistentState: PersistableBundle) {
        super.onSaveInstanceState(outState, outPersistentState)
        NLog.e("[MonitorActivity] onSaveInstanceState ...  ${rinoManager.getChannelName()}")
    }


    private fun createRinoChannel() {
        Log.e("[MonitorActivity] createRinoChannel joinChannel ...  ${rinoManager.getChannelName()}")
        if (rinoManager.getChannelName() != null) {
            rinoManager.joinChannel(mBinding.remoteVideoSurface, agoraId)
        }
//        val sipMsgEvent = MessageEvent(
//            TYPE_CALL_SEND_CREATE_CHANNEL_REQUEST_MONITOR,
//            CallCreateActionBean(channelName = rinoManager.getRemoteChannelName(), aid = agoraId)
//        )
//        EventBus.getDefault().post(sipMsgEvent)
    }

    private fun takeScreenshot(displayName: String = "") {
        val isSuccess =
            ConnectionController.getInstance(applicationContext)
                .takeSnapshot(this@Module_Phone_MonitorActivityNL, displayName)
        Log.e("[jake]....截图结果:  $isSuccess")

    }

    private val coreListener = object : CoreListenerStub() {
        override fun onCallStateChanged(
            core: Core,
            call: Call,
            state: Call.State,
            message: String,
        ) {
            when (state) {
                Call.State.Connected -> {
                    Log.e("[MonitorActivity] onCallStateChanged state:${call.state.name}  callId:${call.callLog.callId} currentCallId:${currentCallId}")
                    if (call.callLog.callId == currentCallId) {
                        //在200 ok里才会携带channelName
                        createRinoChannel()
                        startTimer()
                    }
                }

                Call.State.StreamsRunning -> {
                    if (!isStreamsRunning) {//需要在StreamsRunning状态进行Audio静音操作
//                        manager.setAudioStreamMute(isMute)
//                        rinoManager.stopPushAudioToChannel(agoraId)
                    }
                    isStreamsRunning = true
//                    if (mDialog.isShowing) {
//                        mBinding.tvCallTimer.visibility = View.VISIBLE
//                        initCountdownWorker()
//                        mDialog.dismiss()
//                    }
                }

                Call.State.End, Call.State.Released, Call.State.Error -> {
                    Log.i("[Monitor Activity] Call ended, finish activity")
                    if (currentCallId == call.callLog.callId) {
                        hideLoading()
                        if (EventBus.getDefault().isRegistered(this@Module_Phone_MonitorActivityNL)) {
                            EventBus.getDefault().unregister(this@Module_Phone_MonitorActivityNL)
                        }
                        finish()
                    }
                }

                else -> {}
            }
        }
    }

    private fun initCountdownWorker() {
        if (countdownWorker == null) {
            countdownWorker = Module_Phone_CountdownWorker(countDownTime)
            countdownWorker?.setListener(countdownWorkerListener)
            countdownWorker?.start()
        }
    }

    private val countdownWorkerListener = object : Module_Phone_CountdownWorker.CountdownListener {
        override fun onTick(millisUntilFinished: Long) {
            //从30s开始显示
            val seconds = (millisUntilFinished + 900) / 1000
            val minutes = seconds / 60
            val hours = minutes / 60
            val timeString = String.format("%02d:%02d", minutes % 60, seconds % 60)
            mBinding.tvCallTimer.text = timeString
        }

        override fun onFinish() {
            Log.e("[Monitor Activity] CountDownTimer onFinish")
            mBinding.tvCallTimer.text = "00:00"
            try {
                safeHangup()
            } catch (e: Exception) {
                countdownWorker?.stop()
                countdownWorker = null
            }
            finish()
        }
    }

    private fun initCountdownWidget() {
        mBinding.activeCallTimer.base = SystemClock.elapsedRealtime() + countDownTime
        val sim = SimpleDateFormat("mm:ss")
        mBinding.activeCallTimer.setOnChronometerTickListener {
            val seconds = it.base - SystemClock.elapsedRealtime()
            val displayTime = sim.format(seconds)
            it.text = displayTime
            Log.e("MonitorActivity seconds:$seconds   displayTime:$displayTime")
            if ((SystemClock.elapsedRealtime() - it.base) / 1000 >= 0) {
                safeHangup()
                it.stop()
            }
        }
        mBinding.activeCallTimer.start()
    }

    private fun updateVideoCallParams() {
        manager.setMicEnabled(true)
        Module_Phone_AudioRouteUtils.routeAudioToSpeaker()
        val currentCall: Call? = coreContext.core.currentCall
        val params = coreContext.core.currentCall?.params
        params?.addCustomHeader(NL_Key.CALL_INFO, "")
        currentCall?.update(params)

    }

    private fun muteDevice(isMute: Boolean) {
        rinoManager.setMuteAudio(isMute)
    }

    override fun initColor() {
        initColor(R.color.black)
    }

    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        val action = intent?.action
        if (action.equals("endCall")) {
            finish()
        }
    }

    private val onClickListener = View.OnClickListener { view ->
        when (view.id) {
            R.id.ib_settings -> {
                ARouter.getInstance().build(Base_RouterPath.PATH_DEVICE_SETTING).navigation()
            }

            R.id.remoteVideoSurface -> {

                if (isFullScreen) {
                    if (mBinding.rlBottom.visibility == View.VISIBLE) {
                        NLog.e("hide controllayout")
                        mBinding.rlBottom.visibility = View.GONE
                        mBinding.monitorTitleBar.root.visibility = View.GONE
                    } else {
                        NLog.e("show controllayout")
                        mBinding.rlBottom.visibility = View.VISIBLE
                        mBinding.monitorTitleBar.root.visibility = View.VISIBLE
                    }
                }

            }

            R.id.iv_back -> {
//                setAudioVolume(currentStreamVolume)
                safeHangup()
            }

            R.id.bottom_controller_open_door -> {
                val remoteSipAccount = Module_Phone_VoipController.get().getRemoteSipAccount()
                val currentDevice =
                    getDeviceDataByUsername(remoteSipAccount)
                currentDevice?.doors?.let {
                    if (it.size == 1) {
                        var doorNum = currentDevice.doors?.get(0)?.doorNo ?: 1
                        openDoor(currentDevice.mac, doorNum)
                    } else {
                        showBottomSheetDialog(currentDevice.mac, it)
                    }
                }
            }
        }
    }

    private fun startTimer() {//20s视频流成功未加载,则退出监控界面
        Log.e("[MonitorActivity] startTimer")
        timer?.cancel()
        timer = Timer("Load video stream timeout")
        timer?.schedule(
            object : TimerTask() {
                override fun run() {
                    // Decline call update
                    GlobalScope.launch {
                        withContext(Dispatchers.Main) {
                            com.newlink.building.common_base.ext.showToast(getString(R.string.load_video_error))
                            safeHangup()
                            this@Module_Phone_MonitorActivityNL.finish()
                        }
                    }
                }
            },
            loadVideoTimeout
        )
    }

    private fun stopTimer() {
        Log.e("[MonitorActivity] stopTimer")
        timer?.cancel()
        timer = null
    }


    private fun safeHangup() {
        if (!isFinishing) {
            showLoading()
        }
        countdownWorker?.stop()
        if (joinChannelSuccess) {
            rinoManager.leaveChannel()
        } else {
            val hangUp = manager.hangUp()
            //意外挂掉失败,结束当前Activity
            if (!hangUp) finish()
        }
    }

    override fun onBackPressed() {
        super.onBackPressed()
//        setAudioVolume(currentStreamVolume)
        safeHangup()
    }

    private var mAudioManager: AudioManager? = null

    override fun dispatchKeyEvent(event: KeyEvent): Boolean {
        if (mAudioManager == null) {
            mAudioManager = getSystemService(Service.AUDIO_SERVICE) as AudioManager
        }

        if (event.keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
            if (Module_Phone_Compatibility.volumeDown(this@Module_Phone_MonitorActivityNL, mAudioManager!!)) {
                val v = mAudioManager?.getStreamVolume(AudioManager.STREAM_MUSIC)
                NLog.e(" volume down complete ::: $v")
                return true
            }
        } else if (event.keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
            if (Module_Phone_Compatibility.volumeUp(this@Module_Phone_MonitorActivityNL, mAudioManager!!)) {
                val v = mAudioManager?.getStreamVolume(AudioManager.STREAM_MUSIC)
                NLog.e(" volume up complete ::: $v")
                return true
            }
        }
        return super.dispatchKeyEvent(event)

    }


    override fun onStop() {
        super.onStop()
    }

    override fun onDestroy() {
        super.onDestroy()
        coreContext.inMonitorCallActivity = false
        mBinding.remoteVideoSurface.removeAllViews()
        rinoManager.removeRinoEventListener(rinoEventListener)
        coreContext.core.removeListener(coreListener)
        volumeChangeHelper?.unregisterReceiver()
        timer?.cancel()
        countdownWorker?.stop()
        countdownWorker?.unRegisterListener()
        countdownWorker = null
    }

    private fun showBottomSheetDialog(mac: String, data: MutableList<DoorData>) {
        val bottomSheetDialog = BottomSheetDialog(this, R.style.BottomSheetDialog)
        bottomSheetDialog.setCanceledOnTouchOutside(true)
        val view = LayoutInflater.from(this).inflate(R.layout.bottom_dialog, null, false)
        view.findViewById<TextView>(R.id.center_title).setText(R.string.door_lock_select)
        val recyclerView = view.findViewById<RecyclerView>(R.id.recyclerView)
        view.findViewById<ImageView>(R.id.image_cancel).setOnClickListener {
            bottomSheetDialog.dismiss()
        }

        val dtmfAdapter = Module_Phone_DtmfAdapter(data)
        recyclerView.adapter = dtmfAdapter
        recyclerView.addItemDecoration(SpaceItemDecoration(this))

        dtmfAdapter.setOnItemChildClickListener { _, _, position ->
            openDoor(mac, data[position].doorNo)
            bottomSheetDialog.dismiss()
        }

        bottomSheetDialog.setContentView(view)
        bottomSheetDialog.show()
    }

    private fun openDoor(mac: String, doorNo: Int) {
        showLoading()
        MqttDoorOperator.sendOpenDoorAction(
            userId,
            mac,
            doorNo,
            1
        )
//        KcpTaskHelper.instance.requestOpenDoor(OpenDoorRequest(accessToken,cUserId, KcpRquestType.TYPE_ACTION_OPEN_DOOR,
//            OpenDoorBody(mac = mac, doors = arrayListOf(OpenDoorItem(doorNo,1)))))
    }

//    @Subscribe(threadMode = ThreadMode.MAIN)
//    public fun onOpenDoorResult2(event: OpenDoorResultEvent2) {
//        val reason = event.reason
//        val result = getString(R.string.open_door_result,event.which,if(event.success) getString(R.string.result_success) else getString(R.string.result_failure))
//        val drawable = if(event.success) R.drawable.toast_success_green else R.drawable.toast_failed_red
//        val toast = this?.let {
//            ToastSettingDialog.Builder(it).tittle("").drawable(drawable).message(result).build()
//        }
//        toast?.show()
//    }

//    @Subscribe(threadMode = ThreadMode.MAIN)
//    public fun onOpenDoorResultKcp(event: OpenDoorKcpActionEvent) {
//        showOpenDoorResultDialog(event)
//    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onEventMsgReceived(event: MessageEvent) {
        when (event.msgType) {
            TYPE_APP_OPEN_DOOR_RESULT -> {
                val event = event.msgContent as OpenDoorResultBean
                showOpenDoorResultDialog(event)
            }

            TYPE_CALL_SEND_CREATE_CHANNEL_RESULT_MONITOR -> {
                rinoManager.joinChannel(mBinding.remoteVideoSurface, agoraId)
            }

            TYPE_APP_SHOW_LOADING -> {
                val isShow = event.msgContent as Boolean
                if (!isShow) {
                    hideLoading()
                }
            }

            TYPE_CALL_UPDATE_CHANNEL_RESULT -> {
//                ConnectionController.getInstance(applicationContext)
//                    .takeTempSnapshot(this, tempScreenshotFileName)
//                mBinding.tempScreenShot.visibility = View.VISIBLE

                lifecycleScope.launch {
//                    delay(200)
//                    val imageFile = File(cacheDir, tempScreenshotFileName)
//                    if (imageFile.exists()) {
//                        // 将文件解码为 Bitmap
//                        val bitmap = BitmapFactory.decodeFile(imageFile.absolutePath)
//                        // 设置显示图片
//                        mBinding.tempScreenShot.setImageBitmap(bitmap)
//                    }
                    NLog.e("[MonitorActivity]....TYPE_CALL_UPDATE_CHANNEL_RESULT")
                    //收到远端更新channelName事件,releasePlayer时会退出通道,需要重置加入成功标记
                    joinChannelSuccess = false
                    remoteUpdateChannelEvent = true
                    //卸载播放器
//                    rinoManager.releasePlayer()
                    //两个surfaceView进行切换
                    var newContainer = mBinding.remoteVideoSurfaceBak
                    if (rinoManager.getPlayerContainer() == mBinding.remoteVideoSurfaceBak) {
                        newContainer = mBinding.remoteVideoSurface
                    }
                    rinoManager.cleanJoinChanneJob()
                    //新sdk支持卸载播放器不退出频道功能
                    rinoManager.joinChannel(newContainer, agoraId)
                    newContainer.visibility = View.VISIBLE
                }
            }

            TYPE_CALL_SEND_CREATE_CHANNEL_RESULT_TRYING -> {
                NLog.e("[MonitorActivity]....TYPE_CALL_SEND_CREATE_CHANNEL_RESULT_TRYING")
                rinoManager.joinChannel(mBinding.remoteVideoSurface, agoraId)
            }
        }
    }

    private var currentStreamVolume = 0
    private var volumeChangeHelper: Module_Phone_VolumeChangeHelper? = null

    private fun initVolumeChangeHelper() {
        volumeChangeHelper = Module_Phone_VolumeChangeHelper(this)
        currentStreamVolume = volumeChangeHelper?.getCurrentVoidCallVolume()!!
        Log.e("yxd  currentStreamVolume: $currentStreamVolume")
        volumeChangeHelper?.registerVolumeChangeListener(object :
            Module_Phone_VolumeChangeHelper.VolumeChangeListener {
            override fun onVolumeDownToMin(volume: Int) {
                Log.e("yxd  onVolumeDownToMin: $volume")
                currentStreamVolume = volume
            }

            override fun onVolumeUp(volume: Int) {
                Log.e("yxd  onVolumeUp: $volume")
                currentStreamVolume = volume
            }
        })
    }

    private fun setAudioVolume(index: Int) { // 1-7
        val manager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
        manager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, index, 0)
        Log.e("yxd  setAudioVolume: $index")
    }

    override fun onResume() {
        super.onResume()
        //设置保持屏幕常亮
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
    }

    override fun onPause() {
        super.onPause()
        //取消保持屏幕常亮
        window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
    }

    private fun dismissDialog() {
        NLog.e("[MonitorActivity] dismissDialog $onFirstRemoteVideoFrame")
        if (onFirstRemoteVideoFrame) {
            stopTimer()
            mBinding.tvCallTimer.visibility = View.VISIBLE
            initCountdownWorker()
            mDialog.dismiss()
        }
    }

    private val rinoEventListener = object : RinoEventListenerStub() {
        override fun onJoinChannelSuccess() {
            joinChannelSuccess = true

//            runOnUiThread {
//                //根据设备的连接情况选择相应声道
//                AudioUtils.choiceAudioModel(applicationContext, true)
//            }
        }

        override fun onFirstRemoteVideoFrame() {
            lifecycleScope.launch(Dispatchers.Main) {
                onFirstRemoteVideoFrame = true

                //获取第一帧图像后 再移除绑定的试图
                if (rinoManager.getPlayerContainer() == mBinding.remoteVideoSurface) {
                    if (mBinding.remoteVideoSurfaceBak.isAttachedToWindow) {
                        mBinding.remoteVideoSurfaceBak.removeAllViews()
                    }
                } else {
                    if (mBinding.remoteVideoSurface.isAttachedToWindow) {
                        mBinding.remoteVideoSurface.removeAllViews()
                    }
                }
//                if(rinoManager.getPlayerContainer() == mBinding.remoteVideoSurfaceBak) {
//                    mBinding.remoteVideoSurfaceBak.visibility = View.VISIBLE
//                    mBinding.remoteVideoSurface.visibility = View.GONE
//                }

//                if(rinoManager.getPlayerContainer() == mBinding.remoteVideoSurfaceBak) {
//                    mBinding.remoteVideoSurface.visibility = View.GONE
//                    mBinding.remoteVideoSurface.visibility = View.GONE
//                } else {
//                    mBinding.remoteVideoSurfaceBak.visibility = View.GONE
//                }

                dismissDialog()
            }
        }

        override fun onRemoteVideoStats() {
            ////防止未收到onFirstRemoteVideoFrame事件,状态加载未取消的情况
            lifecycleScope.launch(Dispatchers.Main) {
                if (!onFirstRemoteVideoFrame) {
                    onFirstRemoteVideoFrame = true
                    dismissDialog()
                }
            }
        }

        override fun onLeaveChannel() {
            lifecycleScope.launch(Dispatchers.Main) {
                if (joinChannelSuccess) {
                    //监控中判断有二路来电,已经在coreContext onCallOverlayClick方法里挂断
                    if (coreContext.core.callsNb == 1 && manager.isFirstCallInMonitor()) {
                        val hangUp = manager.hangUp()
                        //意外挂掉失败,结束当前Activity
                        if (!hangUp) finish()
                    }
                    joinChannelSuccess = false
                }
                //远端更新channelName需要重新加入通道
//                if(remoteUpdateChannelEvent) {
//                    rinoManager.joinChannel(mBinding.remoteVideoSurface, agoraId)
//                    remoteUpdateChannelEvent = false
//                }
            }
        }

        override fun onSnapshotTaken(result: Int) {
            runOnUiThread {
                val result =
                    if (result == 0) getString(R.string.result_success) else getString(R.string.result_failure)
                showToast(getString(R.string.function_shortcut_result, result))
            }
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray,
    ) {
        if (requestCode == 100) {
            if (grantResults.isEmpty()) {
                return
            }
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Log.e("[jake] .. get permission of write external storage .... ")
                val remoteSipAccount = Module_Phone_VoipController.get().getRemoteSipAccount()
                val displayName =
                    getDeviceDataByUsername(remoteSipAccount)?.devName ?: Module_Phone_VoipController.get()
                        .getRemoteUsername()
                takeScreenshot(displayName)
            }
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    }

    private var isFullScreen = false
    private var lastClickTime = 0L

    override fun onConfigurationChanged(newConfig: Configuration) {
        super.onConfigurationChanged(newConfig)
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            NLog.e("已切换到横屏")
            updateControllerLayout(true)
        } else {
            NLog.e("已切换到竖屏")
            updateControllerLayout(false)
        }

    }

    private fun toggleFullScreen() {
        val currentTimeMillis = System.currentTimeMillis()
        if (currentTimeMillis - lastClickTime < 800) {
            return
        }

        lastClickTime = currentTimeMillis
        if (isFullScreen) {
            NLog.e(">>>>>>>>>>>>> heng > shu")
            requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
            ibFullscreen?.setImageResource(R.drawable.ic_enter_full_screen)
//            updateControllerLayout(false)
            isFullScreen = false

        } else {
            NLog.e(">>>>>>>>>>>>> shu > heng")
            requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
            ibFullscreen?.setImageResource(R.drawable.ic_exit_full_screen)
//            updateControllerLayout(true)
            isFullScreen = true

        }


    }

    private fun updateStatusbar() {
//        val statusBarHeight = getStatusBarHeight(this@MonitorActivity)
//        statusBarSpace?.layoutParams?.height = statusBarHeight
    }

    private fun updateControllerLayout(isLandscape: Boolean) {

        if (isLandscape) {
            val landscapeHeight = ScreenUtil.getScreenUsableHeight(this@Module_Phone_MonitorActivityNL)
            val landscapeWidth = landscapeHeight * 16 / 9
            NLog.e(">>>>>>>>>>>>> shu > heng  >> height = $landscapeHeight && width = $landscapeWidth")

            val params = RelativeLayout.LayoutParams(
                landscapeWidth,
                landscapeHeight
            ).apply {
                addRule(RelativeLayout.CENTER_HORIZONTAL)
                setMargins(0, 0, 0, 0)
            }

            mBinding.remoteVideoSurface.postDelayed({
                mBinding.remoteVideoSurface.layoutParams = params
                mBinding.remoteVideoSurface.requestLayout()
            }, 120)

            mBinding.remoteVideoSurfaceBak.postDelayed({
                mBinding.remoteVideoSurfaceBak.layoutParams = params
                mBinding.remoteVideoSurfaceBak.requestLayout()
            }, 120)

//            animateViewSizeChange(binding.remoteVideoSurface, landscapeWidth, landscapeHeight, 500)

        } else {

            val height = Base_DensityUtil.dp2px(this@Module_Phone_MonitorActivityNL, 202 + 20)
            val marginTop = Base_DensityUtil.dp2px(this@Module_Phone_MonitorActivityNL, 140 + 20)
            val params = RelativeLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                height
            ).apply {
                addRule(RelativeLayout.CENTER_HORIZONTAL)
                setMargins(0, marginTop, 0, 0)
            }


            mBinding.remoteVideoSurface.postDelayed({
                mBinding.remoteVideoSurface.layoutParams = params
                mBinding.remoteVideoSurface.requestLayout()
            }, 120)

            mBinding.remoteVideoSurfaceBak.postDelayed({
                mBinding.remoteVideoSurfaceBak.layoutParams = params
                mBinding.remoteVideoSurfaceBak.requestLayout()
            }, 120)
//            animateViewSizeChange(binding.remoteVideoSurface,
//                targetWidth = ViewGroup.LayoutParams.MATCH_PARENT,
//                targetHeight = DensityUtil.dp2px(this@CallActivity, 228), duration = 500)
        }

        mBinding.bottomControllerOpenDoorLayout.visibility =
            if (isFullScreen) View.GONE else View.VISIBLE

        funcationKeyData = getFunctionKeyData()
        NLog.e("[CallActivity] > updateControllerLayout ----> funcationKeyData : ${funcationKeyData.size}")
        functionKeyAdapter.apply {
            setNewData(funcationKeyData)
            updateScreenOrientation(isLandscape)
        }

        mBinding.rlFunctions.run {
            adapter = functionKeyAdapter
            val spanCount =
                if (isFullScreen) supportFunctionTypes.size + 1 else supportFunctionTypes.size
            layoutManager = GridLayoutManager(context, spanCount)
        }


        val functionKeyHeight = if (isLandscape) Base_DensityUtil.dp2px(this@Module_Phone_MonitorActivityNL, 60)
        else Base_DensityUtil.dp2px(this@Module_Phone_MonitorActivityNL, 140)

        NLog.e("[CallActivity] > updateController ----> height : $functionKeyHeight")

        mBinding.rlBottom.postDelayed({
            mBinding.rlBottom.layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT
            mBinding.rlBottom.layoutParams.height = functionKeyHeight
            mBinding.rlBottom.requestLayout()
        }, 200)


        val paramsPortal = RelativeLayout.LayoutParams(
            ViewGroup.LayoutParams.WRAP_CONTENT,
            ViewGroup.LayoutParams.WRAP_CONTENT
        ).apply {
            addRule(RelativeLayout.CENTER_HORIZONTAL)
            setMargins(0, Base_DensityUtil.dp2px(this@Module_Phone_MonitorActivityNL, 2), 0, 0)
        }

        val paramsLandscape = RelativeLayout.LayoutParams(
            ViewGroup.LayoutParams.WRAP_CONTENT,
            ViewGroup.LayoutParams.WRAP_CONTENT
        ).apply {
            addRule(RelativeLayout.CENTER_VERTICAL)
            setMargins(
                Base_DensityUtil.dp2px(this@Module_Phone_MonitorActivityNL, 30), 0, 0, 0
            )
        }

        mBinding.tvCallTimer.postDelayed({
            mBinding.tvCallTimer.layoutParams = if (isLandscape) paramsLandscape else paramsPortal
            mBinding.tvCallTimer.requestLayout()
        }, 200)


    }

    //通过call state获取当前的通话
    fun findMonitorCall(): Call? {
        for (call in coreContext.core.calls) {
            Log.e("[Call Activity]  state:${call.state}")
            if (call.state == Call.State.OutgoingInit ||
                call.state == Call.State.OutgoingProgress ||
                call.state == Call.State.OutgoingRinging ||
                call.state == Call.State.OutgoingEarlyMedia ||
                call.state == Call.State.Paused ||
                call.state == Call.State.Pausing
            ) {
                if (call.state == Call.State.Paused || call.state == Call.State.Pausing) {
                    //在MainActivity中由于requestAudioFocus会导致通话处于Pausing,此时需要恢复通话
                    call.resume()
                }
                return call
            }
        }
        return coreContext.core.currentCall
    }
//    private fun toggleFullScreen() {
//        val currentTimeMillis = System.currentTimeMillis()
//        if (currentTimeMillis - lastClickTime < 800) {
//            return
//        }
//
//        lastClickTime = currentTimeMillis
//
//        if (isFullScreen) {
//            NLog.e(">>>>>>>>>>>>> heng > shu")
//            isFullScreen = false
//            ibFullscreen?.setImageResource(R.drawable.ic_enter_full_screen)
//            requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
//            mBinding.remoteVideoSurface.postDelayed({
//                mBinding.remoteVideoSurface.layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT
//                mBinding.remoteVideoSurface.layoutParams.height = DensityUtil.dp2px(this@MonitorActivity , 202)
//                mBinding.remoteVideoSurface.requestLayout()
//            }, 120)
//            updateControllerLayout(false)
//        } else {
//            NLog.e(">>>>>>>>>>>>> shu > heng")
//            requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
//            ibFullscreen?.setImageResource(R.drawable.ic_exit_full_screen)
//            mBinding.remoteVideoSurface.postDelayed({
//                mBinding.remoteVideoSurface.layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT
//                mBinding.remoteVideoSurface.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
//                mBinding.remoteVideoSurface.requestLayout()
//            }, 120)
//            isFullScreen = true
//            updateControllerLayout(true)
//        }
//
//
//    }
//
//    private fun updateControllerLayout(isLandscape: Boolean) {
//
//        functionKeyAdapter.updateScreenOrientation(isLandscape)
//
//
//        val functionKeyHeight = if (isLandscape) DensityUtil.dp2px(this@MonitorActivity, 30)
//        else DensityUtil.dp2px(this@MonitorActivity, 60)
//
//        NLog.e("[CallActivity] > updateController ----> height : $functionKeyHeight")
//
//        mBinding.rlBottom.postDelayed({
//            mBinding.rlBottom.layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT
//            mBinding.rlBottom.layoutParams.height =
//                DensityUtil.dp2px(this@MonitorActivity, functionKeyHeight)
//            mBinding.rlBottom.requestLayout()
//        }, 200)
//
//
//        val paramsPortal = RelativeLayout.LayoutParams(
//            ViewGroup.LayoutParams.WRAP_CONTENT,
//            ViewGroup.LayoutParams.WRAP_CONTENT
//        ).apply {
//            addRule(RelativeLayout.CENTER_HORIZONTAL)
//            setMargins(0, DensityUtil.dp2px(this@MonitorActivity, 9), 0, 0)
//        }
//
//        val paramsLandscape = RelativeLayout.LayoutParams(
//            ViewGroup.LayoutParams.WRAP_CONTENT,
//            ViewGroup.LayoutParams.WRAP_CONTENT
//        ).apply {
//            addRule(RelativeLayout.CENTER_VERTICAL)
//            setMargins(
//                DensityUtil.dp2px(this@MonitorActivity, 30), 0, 0, 0
//            )
//        }
//
//        mBinding.tvCallTimer.postDelayed({
//            mBinding.tvCallTimer.layoutParams = if (isLandscape) paramsLandscape else paramsPortal
//            mBinding.tvCallTimer.requestLayout()
//        }, 200)
//    }

}